package com.jservice.web.base;

import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jservice.framework.dto.Filter;
import com.jservice.framework.dto.Order;
import com.jservice.framework.dto.Pageable;
import com.jservice.framework.dto.Pager;
import com.jservice.framework.utils.StringUtils;
import org.apache.commons.collections.CollectionUtils;

import java.math.BigInteger;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
 * 参考JPRESS 项目 model模块
 * 加入spring事务管理
 */
public class JBaseService<T extends Model> {

	protected static boolean appendWhereOrAnd(StringBuilder builder, boolean needWhere) {
		if (needWhere) {
			builder.append(" WHERE ");
		} else {
			builder.append(" AND ");
		}
		return false;
	}

	protected static boolean appendIfNotEmpty(StringBuilder builder, String colName, String value, List<Object> params,
			boolean needWhere) {
		if (value != null) {
			needWhere = appendWhereOrAnd(builder, needWhere);
			builder.append(" ").append(colName).append(" = ? ");
			params.add(value);
		}
		return needWhere;
	}

	protected static boolean appendIfNotEmpty(StringBuilder builder, String colName, BigInteger value,
			List<Object> params, boolean needWhere) {
		if (value != null) {
			needWhere = appendWhereOrAnd(builder, needWhere);
			builder.append(" ").append(colName).append(" = ? ");
			params.add(value);
		}
		return needWhere;
	}

	protected static boolean appendIfNotEmpty(StringBuilder builder, String colName, Object[] array,
			List<Object> params, boolean needWhere) {
		if (null != array && array.length > 0) {
			needWhere = appendWhereOrAnd(builder, needWhere);
			builder.append(" (");
			for (int i = 0; i < array.length; i++) {
				if (i == 0) {
					builder.append(" ").append(colName).append(" = ? ");
				} else {
					builder.append(" OR ").append(colName).append(" = ? ");
				}
				params.add(array[i]);
			}
			builder.append(" ) ");
		}
		return needWhere;
	}

	protected static boolean appendIfNotEmptyWithLike(StringBuilder builder, String colName, String value,
			List<Object> params, boolean needWhere) {
		if (StringUtils.isNotBlank(value)) {
			needWhere = appendWhereOrAnd(builder, needWhere);
			builder.append(" ").append(colName).append(" like ? ");
			if (value.contains("%")) {
				params.add(value);
			} else {
				params.add("%" + value + "%");
			}

		}
		return needWhere;
	}

	protected static boolean appendIfNotEmptyWithLike(StringBuilder builder, String colName, String[] array,
			List<Object> params, boolean needWhere) {
		if (null != array && array.length > 0) {
			needWhere = appendWhereOrAnd(builder, needWhere);
			builder.append(" (");
			for (int i = 0; i < array.length; i++) {
				if (i == 0) {
					builder.append(" ").append(colName).append(" like ? ");
				} else {
					builder.append(" OR ").append(colName).append(" like ? ");
				}
				String value = array[i];
				if (value.contains("%")) {
					params.add(value);
				} else {
					params.add("%" + value + "%");
				}
			}
			builder.append(" ) ");
		}
		return needWhere;
	}


	public void fillFilters(StringBuffer sb, List param,List<Filter> filters) {
		if (CollectionUtils.isNotEmpty(filters)) {
			sb.append(" where 1=1");
		} else {
			return;
		}
		for (Filter filter : filters) {
			sb.append(" and ");
			sb.append(filter.getProperty());
			switch (filter.getOperator()) {
				case eq:
					sb.append(" = ").append("? ");
					param.add(filter.getValue());
					break;
				case ne:
					sb.append(" <> ").append("? ");
					param.add(filter.getValue());
					break;
				case gt:
					sb.append(" > ").append("? ");
					param.add(filter.getValue());
					break;
				case lt:
					sb.append(" < ").append("? ");
					param.add(filter.getValue());
					break;
				case ge:
					sb.append(" >= ").append("? ");
					param.add(filter.getValue());
					break;
				case le:
					sb.append(" <= ").append("? ");
					param.add(filter.getValue());
					break;
				case like:
					sb.append(" like '").append(filter.getValue()).append("%' ");
					break;
				case in:
					if (filter.getValue() instanceof Collection) {
						List list = (List) filter.getValue();
						sb.append(" in ").append("( ");
						for (int i = 0; i < list.size(); i++) {
							if (i == 0) {
								sb.append(" ? ");
							} else {
								sb.append(",? ");
							}
							param.add(list.get(i));
						}
						sb.append(" ) ");
					}
					break;
				case isNull:
					sb.append(" is null ");
					break;
				case isNotNull:
					sb.append(" is not null ");
					break;
				default:
					break;
			}
		}
	}

	public void fillOrders(StringBuffer sb, List<Order> orders){
		if (CollectionUtils.isNotEmpty(orders)) {
			sb.append(" order by ");
		} else {
			return;
		}
		for(Order order : orders){
			switch (order.getDirection()){
				case asc:
					sb.append(order.getProperty()).append(" asc, ");
					break;
				case desc:
					sb.append(order.getProperty()).append(" desc, ");
					break;
				default:
					break;
			}
		}
		sb.deleteCharAt(sb.lastIndexOf(","));
	}

	public Pager findPage(Pageable pageable , T dao , String tableName ) {
		StringBuffer sb = new StringBuffer(" from ").append(tableName);
		LinkedList<Object> paramValue = new LinkedList<Object>();

		fillFilters(sb,paramValue,pageable.getFilters());
		fillOrders(sb,pageable.getOrders());
		Page page = dao.paginate(pageable.getPageNumber(), pageable.getPageSize(), "select *", sb.toString(), paramValue.toArray());

		Pager pager = new Pager(page.getList(),page.getTotalRow(),page.getTotalPage(),pageable);
		return pager;
	}

}
